package com.session.service;

import com.session.model.Category;
import com.utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class BusinessService {

    private HibernateUtil hibernateUtil = new HibernateUtil();
    private SessionFactory sessionFactory = hibernateUtil.getSessionFactory();

    private void saveFoodCategory() {
        Category foodCategory = new Category("food", new HashSet(), null);
        Category fruitCategory = new Category("fruit", new HashSet(), null);
        Category appleCategory = new Category("apple", new HashSet(), null);

        foodCategory.addChildCategory(fruitCategory);
        fruitCategory.addChildCategory(appleCategory);
        saveOrUpdate(foodCategory);
    }

    private void navigateCategories() {
        Category fruitCategory = findCategoryByName("tomato");
        HashSet categories = new HashSet();

        navigateCategories(fruitCategory, categories);

        for (Object category : categories) {
            System.out.println(((Category) category).getName());
        }
    }
    private void navigateCategories(Category category, Set categories) {
        if (categories.contains(category) || category == null){
            return;
        }
        categories.add(category);

        navigateCategories(category.getParentCategory(), categories);

        Set childCategories = category.getChildCategories();
        if (childCategories == null){
            return;
        }
        for (Object childCategory : childCategories) {
            navigateCategories((Category) childCategory, categories);
        }
    }
    private void saveVegetableCategory() {
        Category foodCategory = findCategoryByName("food");
        Category vegetableCategory = new Category("vegetable", new HashSet(), null);
        foodCategory.addChildCategory(vegetableCategory);
        saveOrUpdate(vegetableCategory);
    }

    private void updateVegetableCategory() {
        Category vegetableCategory = findCategoryByName("vegetable");
        vegetableCategory.setName("green vegetable");
        Category tomatoCategory = new Category("tomato", new HashSet(), null);
        vegetableCategory.addChildCategory(tomatoCategory);
        saveOrUpdate(vegetableCategory);

    }
    private void saveOrangeCategory() {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Category fruitCategory = findCategoryByName(session, "fruit");
            Category orangeCategory = new Category("orange", new HashSet(), null);
            fruitCategory.addChildCategory(orangeCategory);
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
    }
    private void saveOrUpdate(Object object) {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            session.saveOrUpdate(object);
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
    }

    private Category findCategoryByName(String name) {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        Category category = null;
        try {
            tx = session.beginTransaction();
            List results = session.createQuery("from Category as c where c.name='" + name + "'").list();
            category = (Category) results.iterator().next();
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null) {
                tx.rollback();
            }
            throw e;
        } finally {
            session.close();
        }
        return category;
    }

    private Category findCategoryByName(Session session, String name) {
        List results = session.createQuery("from Category as c where c.name='" + name + "'").list();
        return (Category) results.iterator().next();
    }

    private void test() {
        saveFoodCategory();
        saveOrangeCategory();
        saveVegetableCategory();
        updateVegetableCategory();
        navigateCategories();
        sessionFactory.close();
    }

    public static void main(String args[]) {
        new BusinessService().test();
    }
}

